#ifndef __PROCESS_POOL_HPP__
#define __PROCESS_POOL_HPP__

#include <iostream>
#include <cstdlib>
#include <stdio.h>
#include <string>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include <ctime>
#include "Task.hpp"

using callback_t = std::function<void(int fd)>;
const int gdefault_process_num = 5;

class Channle
{
public:
    Channle() {}
    Channle(int fd, std::string &name, pid_t id)
        : _wfd(fd), _name(name), _sub_target(id)
    {
    }
    ~Channle() {}
    void DebugPrint()
    {
        printf("channle name: %s ,wfd: %d,target pid: %d", _name, _wfd, _sub_target);
    }
    int Fd() { return _wfd; }
    std::string Name() { return _name; }
    pid_t Target() { return _sub_target; }
    void Close() { close(_wfd); }
    void Wait()
    {
        pid_t rid = waitpid(_sub_target, nullptr, 0);
        (void)rid;
    }

private:
    int _wfd;
    std::string _name;
    pid_t _sub_target;
};
class ProcessPool
{
private:
    void CtrlSubProcessHelper(int &index)
    {
        // 选择管道
        int who = index;
        index++;
        index %= _channels.size();

        // 选择任务
        int x = rand() % tasks.size();

        std::cout << "选择信道: " << _channels[who].Name() << ", subtarget : " << _channels[who].Target() << std::endl;
        write(_channels[who].Fd(), &x, sizeof(x));
        sleep(1);
    }

public:
    ProcessPool(int num = gdefault_process_num)
        : _processnum(num)
    {
        srand(time(nullptr) ^ getpid() ^ 0x777);
    }
    ~ProcessPool() {}
    bool Initprocesspool(callback_t cb)
    {
        // 建立管道
        for (int i = 0; i < _processnum; i++)
        {
            int pipefd[2];
            int n = pipe(pipefd);
            if (n < 0)
                return false;

            // 创建子进程
            pid_t id = fork();
            if (id < 0)
                return false;
            if (id == 0)
            {
                // 子进程
                for(auto & c:_channels)
                {
                    c.Close();
                }

                close(pipefd[1]);

                cb(pipefd[0]);

                exit(0);
            }
            close(pipefd[0]);
            std::string name = "channel-" + std::to_string(i);
            _channels.emplace_back(pipefd[1], name, id);
        }
        return true;
    }
    // 2. 控制唤醒指定的一个子进程，让该子进程完成指定任务
    // 2.1 轮询选择一个子进程(选择一个信道) -- 负载均衡
    void PoolingCtrlSubProcess()
    {
        int index = 0;
        while (true)
        {
            CtrlSubProcessHelper(index);
        }
    }
    void PollingCtrlSubProcess(int count)
    {
        if (count < 0)
            return;
        int index = 0;
        while (count)
        {
            CtrlSubProcessHelper(index);
            count--;
        }
    }
    void WaitSubProcesses()
    {
        // for(int end = _channels.size()-1; end >= 0; end--)
        // {
        //     _channels[end].Close();
        //     _channels[end].Wait();
        // }
        for (auto &c : _channels)
        {
            c.Close();
            c.Wait();
        }
        // // 1. 先让所有子进程结束
        // for (auto &c : _channels)
        // {
        //     c.Close();
        // }
        // // 2. 你在回收所有的子进程僵尸状态
        // for (auto &c : _channels)
        // {
        //     c.Wait();
        //     std::cout << "回收子进程: " << c.Target() << std::endl;
        // }
    }

private:
    std::vector<Channle> _channels;
    int _processnum;
};

#endif